八皇后问题---详解---参考<<紫书>>
在一个8*8的棋盘上 放置八个皇后 , 使得他们互相不攻击(皇后攻击范围为 同行同列同对角线) ,
方法一 :
从64个格子中 选一个子集 , 使得 " 子集 中恰好有八个元素 , 且任意选出的两个格子都不是同一行,同一列同,一对角线" , 这是子集枚举问题 , 然而 , 64个格子的自己有2^64个 , 所需处理数据过大 !
方法二:
从64个格子中 选八个格子 , 称为组合生成问题 , 根据组合数学 有 4.426*10^9中方案 , 虽然比第一种好 , 但是然并卵 .
---------------------------我是分割线--------------------------------------
经过思考你会不难发现下面一种方法 , 每一行每一列恰好会放一个皇后 , 所以可以从第一行开始放 , 然后考虑第二行 , 依次进行 下去 !
这样就变成了全排列生成问题 , 这样的排列有 8! = 40320个 , 枚举量不会超过该数字
然而 如果每次都枚举这么多次的话 也会超时的 , 所以我们可以采用回溯的方法 或者 用 上/下一个排列 .
1 // 这是一种很常用的方法 ,平时的搜索 都是这 一种形式 2 #include<stdio.h> 3 #include<string.h> 4 #include<math.h> 5 #include<iostream> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #include<set> 11 #include<stack> 12 using namespace std; 13 int tot,c[1000],vis[3][1000],n,a[11]; 14 void search(int cur) 15 { 16 if(cur==n) 17 tot++; 18 else 19 for(int i=0;i<n;i++) 20 { 21 if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n]) 22 { 23 c[cur]=i; 24 vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=1; 25 search(cur+1); 26 vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=0; 27 } 28 } 29 } 30 int main() 31 { 32 for(n=1;n<=10;n++) 33 { 34 tot=0; 35 memset(c,0,sizeof(c)); 36 memset(vis,0,sizeof(vis)); 37 search(0); 38 a[n]=tot; 39 } 40 while(scanf("%d",&n),n) 41 { 42 printf("%d\n",a[n]); 43 } 44 return 0; 45 }
下面附上另一个用时最短0ms 并且 容易理解的
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue> 7 #include<vector> 8 #include<map> 9 #include<set> 10 #include<stack> 11 using namespace std; 12 int n,c[10],tot,a[11]; 13 void search(int cur) 14 { 15 if(cur==n) //递归边界 , 只要走到了这里 , 所有皇后必然不冲突 . 16 tot++; 17 else 18 for(int i=0;i<n;i++) 19 { 20 int ok=1; 21 c[cur]=i; // 尝试将 cur 行的 皇后放在 i 列 . 22 for(int j=0;j<cur;j++) // 检查是否 个 前面的皇后冲突 23 { 24 if(c[cur]==c[j]||cur-c[cur]==j-c[j]||cur+c[cur]==j+c[j]) // 25 { 26 ok=0; 27 break; 28 } 29 } 30 if(ok) 31 search(cur+1); 32 } 33 } 34 int main() 35 { 36 for(n=1;n<=10;n++) 37 { 38 memset(c,0,sizeof(c)); 39 tot=0; 40 search(0); 41 a[n]=tot; 42 } 43 while(scanf("%d",&n),n) // 几皇后 ? 44 { 45 printf("%d\n",a[n]); 46 } 47 }